trigger CheckforAttachment on Opportunity (before update) 
   {
    string[] strprdarray=new string[]{'TV General Market','TV Other','TV Direct Response'};
    Set<ID> oppAASRecordTypeID = AASFieldUpdateHelperClass.getOpportunityAASRecordTypeID();
    Map<Id,List<Opportunity_Attachments_Classification__c>> mapattchtype=new Map<Id,List<Opportunity_Attachments_Classification__c>>();
    List<Opportunity>  lstopp=[Select StageName,(Select id,Attachment_Type__c,AttachmentId__c from Opportunity_Attachments_Classification__r where Attachment_Type__c='IO')
    From Opportunity where id in :trigger.new and recordtypeId=:oppAASRecordTypeID];
    for(Opportunity opp:lstopp)
    {
        List<Opportunity_Attachments_Classification__c> lstattachmentType=opp.Opportunity_Attachments_Classification__r;
        mapattchtype.put(opp.Id,lstattachmentType);
    }
    Map<Id,List<OpportunityLineItem>> mapOLI=new Map<Id,List<OpportunityLineItem>>();
    for(Opportunity opp:[Select id,(Select OpportunityId,PricebookEntry.Product2.Family From OpportunityLineItems where PricebookEntry.Product2.Family  in:strprdarray) From Opportunity where Id in:trigger.new])
    {
        List<OpportunityLineItem> lstOpportunityLineItem=opp.OpportunityLineItems;
        mapOLI.put(opp.Id,lstOpportunityLineItem);
    }
  

    for(Opportunity opp:trigger.new)
    {
         if(opp.StageName=='Signed' && trigger.oldmap.get(opp.Id).StageName!='Signed')
        {
            List<Opportunity_Attachments_Classification__c> lstattachmentType=mapattchtype.get(opp.Id);
            List<OpportunityLineItem> LstOpplineItem=mapOLI.get(opp.Id);
            if(lstattachmentType.size()==0 && LstOpplineItem.size()==0)
            {
            opp.addError('  Unable to change Opportunity Stage to \'Signed\'. You must go to the Attachments section below, click on the Attach File button to upload a signed IO document in order to proceed.');
            }
            
        }
    }
    
}